< Back

Quest 7: Project - Easy Transfers

Availability
Ended
Quest master
StackUp
Est. time
1 hour(s)
Your status
Rejected
View feedback
Reward
$8
No. of rewards
525
Start date
17 Feb 2023, 9:30 am
Deadline
28 Feb 2023, 9:30 am
Review by
10 Mar 2023, 9:30 am
Created
03 Feb 2023, 11:57 pm
Introduction
In the previous quests, you learned all about USDC and Circle's APIs. In this quest, we will be writing and running a simple payment application that allows a user to transfer USDC via a smart contract with their own MetaMask wallet.
Note: This quest requires you to have knowledge of the use of the Accounts API which is covered in Quest 6: Accounts API. If you have not gone through this quest yet, please do so.

For queries on this quest, join our Discord, head to the #circle-helpdesk channel and look for this quest's post.

In the event that you are not able to view certain quest steps, you may head here.
Learning Outcomes
By the end of this quest, you will be able to: 
  • Set up your MetaMask wallet
  • Import USDC token into MetaMask wallet
  • Write and deploy a Smart Contract on Remix IDE
  • Run a simple payment application that allows the transfer of USDC and interacting with smart contract

Deliverable
To successfully complete this quest, you will need to do the following: 
  1. Screenshot of the deployed smart contract on Etherscan Goerli Testnet Network. See Step 4 for details. 
  2. Screenshot of USDC transfer transaction details on Etherscan Goerli Testnet Network. See Step 6 for details. 

In the event that you are not able to view certain quest steps, you may head here.

Questing solo?

Discuss about this quest with your fellow Stackies on Discord! They're a friendly bunch and always down to lend a hand.
Quest Walkthrough
Step 1: Set Up and Install MetaMask Wallet
Note: You may skip this step if you already have your own MetaMask wallet. 
In this step, you will be creating your own MetaMask wallet. MetaMask is a crypto wallet and gateway to blockchain apps where users can buy, store, send and swap tokens. MetaMask is available as a browser extension and as a mobile app. In this quest, we will be creating a wallet on your web browser.

  1. Firstly, go to MetaMask and click on the download button for your browser. For this example, we will be using the Google Chrome browser.
  2. You will be redirected to your browser's webstore. Click on 'Add to Chrome', then click add extension.
  3. Afterwards, a new tab will pop up showing a welcome message. Click on 'Get started'.
  4. Next, on the ‘Help us improve MetaMask Page’, click on I agree. Then click on 'Create a wallet'.
  5. On the next page, create a password. This password is used to access your MetaMask wallet account.
  6. After that, you will be redirected to the ‘Secure your wallet’ page where there will be a short video explaining to you the importance of your Secret Recovery Phrase. After watching the video, click on 'Next'.
  7. You will be redirected to the 'Secret Recovery Phrase' page. Click on ‘Click here to reveal secret words’, take down the recovery phrase, and store it in a safe place. Do not lose it or tell anyone. Click on the Next button.
  8. On the next page, you will need to confirm the Secret Recovery Phrase that you copied previously. Select the key phrases in the right order in order to proceed.
  9. If the Secret Recovery key phrase is entered correctly, you will be shown the homepage of MetaMask which has your wallet address, as shown in 'expected output'. You have successfully created your MetaMask Wallet.
  10. For easier access to your MetaMask wallet, you can pin the MetaMask extension onto your browser.
  11. The MetaMask wallet icon will now appear on the top right-hand corner of your screen.
Expected output
Step 2: Using MetaMask with the Goerli Testnet
Connect to Goerli Testnet Network By default, Ethererum is selected as the default network. In this quest, we will use the Goerli test network to make transactions.

Click on the ‘Ethereum Mainnet’ located at the top of the MetaMask window and select 'Goerli test network'. In the event that you do not see it, head to your Settings, select Advanced and turn on the 'Show test networks' switch. 

Your selected network will be switched to the Goerli test network. At this point, notice that we do not have any GoerliETH available. 


Obtaining GoerliETH from a Goerli Faucet
A faucet is a dispenser where developers can request testnet tokens for testing before going into the mainnet. When a wallet is newly created, there will not be any GoerliETH available in the wallet. 

Firstly, head to this Goerli faucet. You will need to sign up for an Alchemy account in order to have GoerliETH sent to you. 

After signing up, copy your MetaMask wallet address by clicking on it at the top of the MetaMask pop-up and input it into the field and click ‘Send Me ETH’.

The transaction will eventually show up as a successful response, as seen in 'expected output'.

When checking your MetaMask wallet, the balance should be updated.
Expected output
Step 3: Transfer USDC to your MetaMask Wallet
How to start
Import USDC token into Metamask Wallet Go to your MetaMask wallet and click on ‘Import tokens’ at the bottom of the window.

Next, enter 0x07865c6E87B9F70255377e024ace6630C1Eaa37F as the contract address. The token symbol and decimal places will be automatically populated. Click on ‘Add custom token’. You can view and verify the USDC token contract address here to ensure that you are adding the legitimate token. 

In the next screen, click on ‘Import tokens’.

Return to your account, and under the Assets tab, the USDC token will appear. 

Obtaining USDC

As we do not have any USDC tokens in the MetaMask wallet, we will need to make a transfer. We will use the Circle Accounts API just as we did in Quest 6 to make the transfer. Open up Postman, go to Accounts API ‘Transfers’ folder and click on ‘Create a Transfer’, as shown in 'how to start'.

In the authorization tab, change the type to 'Bearer Token’ and ensure your API key is input into the token field. Now click on the body tab, and enter the JSON data below as your body.

Generate a new uuid and replace the idempotencyKey value with it. Then replace the destination address with your MetaMask wallet address. You can replace the amount with any existing USDC amount you have in your Circle-hosted wallet. Your Body should look like this:
{   "idempotencyKey": "REPLACE_WITH_NEW_UUID",   "source": {     "type": "wallet",     "id": "REPLACE_WITH_YOUR_CIRCLE_WALLET_ID"   },   "destination": {     "type": "blockchain",     "address": "REPLACE_WITH_YOUR_METAMASK_WALLET_ADDRESS",     "chain": "ETH"   },   "amount": {     "amount": "100",     "currency": "USD"   } }

Now click ‘Send’. You will receive a response with a pending status, as shown in 'expected output'.

After a minute or so, click on the send button with the same IdempotencyKey and the transaction status should be displayed as complete. Your MetaMask USDC token balance should be updated with the amount you have sent from your Circle wallet.

Note: you can also obtain USDC from this faucet but the amount of USDC to receive cannot be set by the user.
Expected output
Step 4: Write and Deploy a USDC Smart Contract for Transfers
In this step, we will be writing a smart contract to enable the transfer of USDC from a sender to its intended recipient without a trusted intermediary like a bank. By writing the smart contract, we will be able to send and receive USDC. This leads to a secure and automated process which will benefit both sender and recipient. Once the smart contract is deployed to the Goerli testnet, we will be able to build our app by referring to functions within the smart contract.
Since we have both USDC and GoerliETH tokens in our MetaMask wallet, we can start writing the smart contract to the Goerli test network using Remix Integrated Development Environment (IDE). Stackies who have completed Solidity campaigns previously would be familiar with Remix IDE. 

An IDE is basically software used to build applications using common developer tools in a graphical user interface. Remix IDE is an open-source Ethereum IDE you can use to write, compile and debug Solidity code. Remix IDE is available on 2 platforms – Remix Online IDE and Remix Desktop IDE. For this quest, we will be using the Remix Online IDE. 

First head over to the Remix Online IDE. Let's create a new file in the root directory and name it UsdcDemo.sol. To create a new file, click on the new file icon
below the words 'default_workspace'. Your new file should now appear below README.txt

Next, update the UsdcDemo.sol file with the following code snippet.
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; // Abstract interface USDC {   function balanceOf(address account) external view returns (uint256);   function allowance(address owner, address spender) external view returns (uint256);   function transfer(address recipient, uint256 amount) external returns (bool);   function approve(address spender, uint256 amount) external returns (bool);   function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); } // Contract contract UsdcDemo{   USDC public USDc;   // Contract Owner   address payable public owner;   constructor(address usdcContractAddress) {     USDc = USDC(usdcContractAddress);     // User who is calling this function address     owner = payable(msg.sender);   }   function Fund(uint $USDC, address recipient) public payable {     // Transfer USDC to this contract from the sender account     USDc.transferFrom(msg.sender, address(this), $USDC * 10 ** 6);      // Transfer to the recipient     USDc.transfer(recipient, $USDC * 10 ** 6);    } }

Now let's understand the code in smaller sections.



The code snippet above creates an interface to utilize the function created on the main USDC smart contract at Goerli test network. The balanceOf function takes in an address variable and returns the account balance in the form of an integer. The allowance function returns the token amount remaining, which the spender is currently allowed to withdraw from the owner's account. 



When viewing the Application Binary Interface (ABI), we are referring to the allowance and balanceOf functions in our smart contract. This is so that we can call those functions later on in the front end to check the balance of USDC in the user wallet or give the dApp permission for it to spend your tokens on your behalf when initiating a transfer. The ABI is the standard way to interact with contracts in the Ethereum ecosystem, both from outside the blockchain and for contract-to-contract interaction.

You can even test out the functions there by clicking on them, inputting the arguments needed, and clicking query. In the example below, a query of an address returns the balance of USDC in the MetaMask wallet. The value returned below needs to be divided by 1000000 due to the USDC token having 6 decimal places.


Next, click on the ’Write as Proxy’ tab and you should see the approve function at the top. Scroll down to find the transfer and transferFrom functions. The approve function takes in the address of the spender and amount and returns a boolean value indicating if the token holder has approved an allowance for the contract to spend or transfer out.



The transferFrom function takes in the address of the sender, recipient, and USDC amount as parameters in order to transfer USDC to the current contract from the sender account. USDC is then sent to the recipient address using the transfer function.

In the next section of the code snippet, we created a contract instance ‘UsdcDemo’.



A constructor is also declared. A constructor in Solidity is a special function that is used to initialize state variables in a contract. The constructor is called when a contract is first created and can be used to set initial values. 

In the last section of the code snippet, we created a Fund function. The function accepts two parameters – the amount the connected account is willing to fund and its intended recipient. Inside this function, we utilized the transferFrom function from the interface to transfer the desired amount from the user to the contract, and then we sent it to the recipient using the transfer function.



Compile and Deploy the Smart Contract

In this section, we will compile the USDC-based smart contract we wrote in the previous section. Click on the compiler tab, change the compiler version to the latest version and click 'Compile UsdcDemo.sol'.



Next, go to the Deployment tab and change the selected environment to Injected Provider - MetaMask as we will be using the MetaMask wallet to deploy the smart contract.



The MetaMask pop-up will show up asking you which account you want to use to connect with the site. Click 'Next' and connect. Your wallet will then show up in the Account field.

Next, for the Contract field, select the contract UsdcDemo - UsdcDemo.sol that we want to deploy.



Next, paste the original USDC contract address 0x07865c6E87B9F70255377e024ace6630C1Eaa37F into the field beside the deploy button and click the Deploy button, as shown below.



MetaMask will prompt for the confirmation of the request. Click 'Confirm'. Afterwards, a deployment message will be shown on the console suggesting that the contract has successfully been deployed on the Goerli Ethereum Network. Return to your MetaMask wallet, and the contract deployment activity will be shown under the Activity tab. Keep the Remix browser window open as we will need it later.

In your MetaMask, click on the contract deployment activity and click on ‘View on block explorer’.



A new window will pop up, redirecting you to the block explorer with your smart contract creation transaction details. Take note of your smart contract address as we need it in the next step. 

Important: At this point, take a full screenshot of your Etherscan page with your MetaMask wallet extension opened. Refer to the 'Expected Output' to see what your screenshot should look like. You will need this for your submission later. 

You can click on the contract address in blue font and track the activities that interact with the smart contract such as contract creation, as shown in the image below. Do not close this page yet as you will need the information on this page in the next step.

Expected output
Step 5: Writing and Running a Simple Payment App for Easy Transfers
Project Setup
In this step, we will be cloning a GitHub repository containing files needed to run a simple payment application for transferring USDC from wallet to wallet.

First, open up a terminal and clone the git repository into the directory of your choice.
git clone -b circle-quest-7 https://github.com/stackup-dev/circle-campaign.git circle-quest-7

Next, run the following command to access the directory where the repository is cloned.
cd circle-quest-7

Finally, let’s install the required npm packages by running the following command.
npm install

Update Contract ABI

In this section, we will update the project smart contract address and contract Application Binary Interface (ABI) with our own that we just built and deployed. The ABI is the standard way to interact with contracts in the Ethereum ecosystem, both from outside the blockchain and for contract-to-contract interaction.

In Remix IDE, copy the contract ABI as shown below. Ensure the contract UsdcDemo(UsdcDemo.sol) is selected.



Using a code editor of your choice (in our case we will be using Visual Studio Code), open utils/fundUSDC.json, remove all the code in it and paste the ABI you copied. It should be the same as the existing data but possibly in a different order.



Understanding and Completing index.tsx
In the previous step, you were told to click on your contract address and to keep the browser tab open. Near the top of the contract address page, copy the deployed contract address from the block explorer by clicking on the copy icon, as shown in the image below.



Go to the pages folder and open index.tsx. In line 18, paste the contract address over REPLACE WITH YOUR SMART CONTRACT ADDRESS.

Let’s understand what's happening in this file!



In the code snippet above, we imported the ABI files from the utils folder for both the original USDC contract (usdcContract.json) as well as the USDC-based contract we deployed (fundUSDC.json). We will need to refer to these values later when creating a contract instance.



In the code snippet above, we declared variables that are used in the whole application. Firstly, in lines 16 and 18, we assigned the smart contract addresses to their respective variables. The contractABI variable in line 23 is assigned to the ABI file we imported in line 11. The rest of the variables from line 25 onwards represent the status of the application like sending, approving, and isApproved. The other variables will be displayed in the application for viewing like currentAccount, USDCBalance and amount.



Next, let's understand the getBalance function. This function takes in an address string variable as a parameter and aims to set the USDC balance of the address parsed in. In lines 36 and 37, we will be using the ethers library to establish a connection with our MetaMask Ethereum wallet address and get the account signer. 

Next, we will fill in code to complete the getBalance function. Firstly, let’s create a contract object instance starting at line 40. We will create the contract instance using the ethers.Contract function which requires 3 parameters – the contract Address, ABI and signer. With the contract instance initialized, we can then move on to use the functions in the original USDC smart contract to get the balance of the wallet address.
  // Create a contract object   const usdcContract = new ethers.Contract(    originalUsdcContract,    usdcAbi,    signer   );

We will now use the contract instance to refer to the functions to get the USDC balance. We will use the balanceOf function that takes in an address as its parameters. It returns the balance of USDC in the wallet address and we will set it using the setUSDCBalance state function.
  // Use the balanceOf function to get wallet USDC balance   const balance = await usdcContract.balanceOf(address);   //set variable value   setUSDCBalance(balance / 1000000);

The full completed code of the function should be similar to the image below.



Let’s move on to the connectWallet function. The function is triggered with a button click which will allow us to connect our MetaMask wallet. We will be filling in code segmented into 3 parts.



In the first part, we will be using Ethereum JSON-RPC API's eth_requestAccounts method to get our wallet address. Refer to the documentation for more information on the methods used. Copy and paste the following code below "//Get user MetaMask Ethereum wallet address".
   // Get user Metamask Ethereum wallet address    const accounts = await ethereum.request({     method: "eth_requestAccounts",    });

The function below returns an array of account addresses. In this case, we will be taking the first wallet address in the array and set the value using the setCurrentAccount state function. Copy the code below and add it to your file.
   // Get the first account address and assign to variable    setCurrentAccount(accounts[0]);

Now that we have our MetaMask wallet address, we will call the getBalance function we wrote in the previous section to retrieve the USDC balance of this connected wallet. Copy the code below and add it to your file.
   //get wallet balance - call getBalance() function    await getBalance(accounts[0]);

By now, the connectWallet function should look like this if you have copied the code over correctly:



We will move on to the Fund function (line 107) next, which will allow the user to call the fund function written in our deployed smart contract to initialize the transfer of USDC tokens to our intended recipient. We will be filling in code to complete the functions in 2 parts – look out for the two parts that say '(fill in code here)'.

Recall that earlier we already initialized a contract instance fundContract with our deployed contract with the ethers.Contract method earlier in the getBalance function.

Now we will call the fund function in our smart contract using our contract instance. The fund function written in the smart contract we deployed takes in 2 parameters - the amount we want to transfer and address of the recipient receiving the USDC tokens. Copy the code below to the first '(fill in code here)'. 
   // Send the transaction, call the Fund function in the contract    const Txn = await fundContract.Fund(amount, receiverAddress, {        gasLimit: 300000,       });

Lastly, we will need the transaction to be completed and confirmed in the blockchain.
Simply use the wait function to do that. Copy the code below to the second '(fill in code here)'. 
   // Wait for the transaction to be mined    await Txn.wait();

The completed function should look something like the following:



Moving on to the approve function (line 153), this function checks if the user has approved the contract to spend their USDC on their behalf. Similar to the Fund contract earlier, we will be filling code in 2 parts to call the approve function from the contract and waiting for the transaction to be completed – look out for the '(fill in code here)' prompts. 

In the first part, we will use the contract instance usdcContract initialized to call the approve function. The approve function takes in the address of spender and the amount of USDC tokens as its 2 parameters. Copy the code below to the first '(fill in code here)'. 
    // Use the approve function to send USDC to the contract     const usdcTxn = await usdcContract.approve(      usdcDemoContract,      ethers.utils.parseUnits("1000", 6)     );

Lastly, we will need the transaction to be completed and confirmed in the blockchain.
We will use the wait function to do that. Copy the code below to the second '(fill in code here)'. 
    // Wait for the transaction to be mined     await usdcTxn.wait();

The completed function should look something like the following:

Step 6: Running the Application
Now that we have completed the code for the application, it is time to run the application to test it out.
Open a terminal and ensure you are in the same directory as the project by using the command:
cd circle-quest-7

Next, run the following command to start the application in your localhost.
npm run dev

The following output will be shown in your terminal.



Enter http://localhost:3000 in your browser. The application will be running.



Connect your MetaMask wallet by clicking on the ‘Connect Your MetaMask Wallet’ button.
A pop-up from MetaMask will appear, click 'Next' and then 'Connect'. Your wallet address and USDC balance amount will appear at the top of the site.

Click the ‘I want to send USDC’ button. This button will trigger the approve function in the code to give the contract permission to access your USDC token. A pop-up will appear from MetaMask asking for permission to access your USDC, click ‘Confirm’. 



The transaction process will take a while. After it is completed, you will be shown two fields to input wallet address and USDC amount, and a button to send USDC tokens.

 

In the first field, enter the address of the recipient wallet address, which can be another Ethereum address. In this case, let's try sending it to the ETH address that we created in the Circle Accounts API in Quest 5 which is linked to our Circle master wallet identifier. Note: Do not input your Circle master wallet identifier. Otherwise, you will receive an error about the field not being configured for ENS name. In the event you have lost the address, you may head to Step 8 for instructions on how to retrieve the address. For the USDC amount, indicate 6.

Click on the ‘Send USDC now’ button. The button click triggers the fund function written in the code. A pop-up appears asking for you to confirm and sign the transaction. Click 'Confirm'. Wait for the transaction to be completed. Your USDC balance of your MetaMask wallet will reflects its new balance.

Troubleshooting
  • If you receive an error message of 'fundContract.Fund is not a function', it likely means that you made a mistake in Step 5. Check that you copied the ABI correctly. 
  • If you receive an error of 'cannot estimate gas; transaction may fail or may require manual gas limit', check that you inserted the correct contract address in line 18 of index.tsx as mentioned in Step 5.

Now, to view the transaction, head to the Circle Sandbox and log in. On the Merchant Payments page, in the Transfers tab, you will be able to see the transaction of USDC sent to your Circle account.



Click on the transaction and you will be directed to a page showing a summary of the transaction, including the source, destination, status, transaction hash, and a link to view the transaction on the block explorer. Click to view the transaction on the block explorer, and you will be led to Etherscan.  

Notice the 'Interacted With (To):' section contains the address of the smart contract that we deployed earlier. 

Important: At this point, take a full screenshot of your Etherscan page. You will need it for your submission later. Refer to the 'Expected Output' to see your screenshot should look like. 
Expected output
Step 7: Let’s Ace Your Submissions! Preparing Your Submission!
You have reached the end! Now to ensure you successfully complete this quest! There are 2 screenshots that you need to submit.
In Step 4, you had to take a screenshot of your entire screen showing a successful contract creation on Etherscan. 

Your screenshot should show:
  • your full screen, including your taskbar (for Windows and Linux) / dock (for MacOS)
  • Your MetaMask wallet extension open with the Activity tab showing Contract deployment
  • The address of the smart contract deployed
  • All parts in red boxes in Step 4's ‘Expected Output’ are visible in your screenshot!

When labelling your screenshot, make sure to follow the format provided: C58_Q7_yourstackupname_1.png.

In Step 6, you had to take a screenshot of your entire screen showing a successful transfer of USDC tokens on Etherscan. 

Your screenshot should show:
  • your full screen, including your taskbar (for Windows and Linux) / dock (for MacOS)
  • Address of the smart contract that was deployed in Step 4
  • Transfer of USDC tokens from your MetaMask wallet to the contract, and then to another address
  • All parts in red boxes in Step 6's ‘Expected Output’ are visible in your screenshot!

When labelling your screenshot, make sure to follow the format provided: C58_Q7_yourstackupname_2.png.
Step 8: Retrieve Your Blockchain Address from Quest 5 (Optional)
Open up Postman, go to Accounts API's wallet directory and select ‘List all addresses’.


In the authorization tab, change the type to 'Bearer Token’ and ensure your API key is input into the token field. 


 
Next, click on the Params tab and input your Circle master wallet identifier in the value field of the walletId key.



Then click send. A successful response will show a list of blockchain addresses created with your master wallet identifier. 

Back to Campaign
Enabling Payments with Circle
StackUp
KiranKumar
Current: US$15.00
Timezone: Asia/Calcutta
Home
Profile
Earn
Campaigns
Quests
Bounties
My Progress
Learn
Calendar
Help
T&Cs
StackUp © 2023